package megrez.bussiness.system.web.rest;

import static org.springframework.util.StringUtils.hasText;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
import megrez.bussiness.system.entity.Dept;
import megrez.bussiness.system.repository.DeptRepository;
import megrez.bussiness.system.repository.DeptSpecification;
import megrez.bussiness.system.service.DeptService;
import megrez.bussiness.system.web.dto.DeptDto;
import megrez.bussiness.system.web.mapper.DeptMapper;

/**
 * 部门接口
 * 
 * @author Lucky Yang
 * @since 0.0.1
 */
@RestController
@RequestMapping("/v1/depts")
@RequiredArgsConstructor
public class DeptResource {
    private final DeptRepository deptRepository;
    private final DeptService deptService;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public String create(@RequestParam(name = "parentId", required = false) Long parentId,
            @RequestBody DeptDto deptDto) {
        Dept entity = deptService.save(parentId, DeptMapper.INST.toEntity(deptDto));
        return entity.getId().toString();
    }

    @PutMapping("/{id}")
    public void update(@PathVariable("id") Long id, @RequestBody DeptDto deptDto) {
        deptService.update(id, DeptMapper.INST.toEntity(deptDto));
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable("id") Long id) {
        deptService.delete(id);
    }

    @GetMapping("/code-name")
    public Map<String, String> getCodeName() {
        return deptService.getCodeNameMap();
    }

    @GetMapping
    public List<DeptDto> get(@RequestParam(name = "onlyTop", required = false) Boolean onlyTop,
            @RequestParam(name = "name", required = false) String name,
            @RequestParam(name = "enabled", required = false) Boolean enabled) {
        Specification<Dept> where = Specification
                .where(Boolean.TRUE.equals(onlyTop) ? DeptSpecification.parentIsNull() : null)
                .and(hasText(name) ? DeptSpecification.nameLike(name) : null)
                .and(enabled != null ? DeptSpecification.enableEqual(enabled) : null);

        List<Dept> entities = deptRepository.findAll(where);
        Collections.sort(entities, Comparator.comparing(Dept::getPathCode));
        return DeptMapper.INST.toDto(entities);
    }

    @GetMapping("/{id}/children")
    public List<DeptDto> getChildren(@PathVariable("id") Long id) {
        Dept parent = deptService.findById(id);
        List<Dept> entities = deptRepository.findByParent(parent);
        Collections.sort(entities, Comparator.comparing(Dept::getOrderNo));
        return DeptMapper.INST.toDto(entities);
    }

    @GetMapping("/{id}/grandchildren")
    public List<DeptDto> getGrandchildren(@PathVariable("id") Long id) {
        List<Dept> entities = deptService.getGrandchildren(id);
        return DeptMapper.INST.toDto(entities);
    }

    @GetMapping("/{id}")
    public DeptDto getById(@PathVariable("id") Long id) {
        Dept entity = deptService.findById(id);
        return DeptMapper.INST.toDto(entity);
    }
}
